from sqlalchemy import and_
from datetime import datetime
from sqlalchemy import or_
import os

from flask import Flask,render_template,request,jsonify,redirect, url_for, session
import json
from werkzeug.utils import secure_filename

from ai_scoring import scoring

# 先创建Flask应用实例
app = Flask(__name__)

# 导入配置
from config import Config
app.config.from_object(Config)
app.secret_key = 'ABC'

# 配置上传文件参数
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB限制
app.config['UPLOAD_FOLDER'] = 'static/pdf'
app.config['ALLOWED_EXTENSIONS'] = {'pdf'}

# 确保上传目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)


# 导入数据库
from models import db

# 现在导入数据库和模型

from datetime import datetime, timedelta

from sqlalchemy import func


# 初始化数据库
db.init_app(app)

# 在数据库初始化后导入模型
from models import QuestionBank,Exam,Class,ExamClass,Test2question,Test_paper,Answer,Teacher,Student

# 注册蓝图（在数据库和模型初始化后）
from create_exams import create_examsbp
app.register_blueprint(create_examsbp)

# 注册批改蓝图
from Correction_new import correction
app.register_blueprint(correction)

# 其他导入（这些模块可能依赖于db，所以放在db初始化之后）
from AI_generate import ai_generate
from pdf_questions import pdf_questions as pdf_q
from exam_pepar import api_identify_questions
from exam_set import ExamImporter

exam_importer = ExamImporter(app.config['UPLOAD_FOLDER'])
ALLOWED_EXAM_EXTENSIONS = {'xml', 'json'}

# 确保在应用上下文中执行数据库操作
def create_tables():
    # 在应用上下文中创建所有表
    with app.app_context():
        try:
            db.create_all()
            print("使用Flask-SQLAlchemy创建表成功")
        except Exception as e2:
            print(f"使用Flask-SQLAlchemy创建表失败: {e2}")

# 在应用启动时创建表
create_tables()

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
def allowed_exam_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXAM_EXTENSIONS

@app.route('/api/current-user')
def get_current_user():
    """获取当前用户信息的API接口"""
    user_info = {
        'identity': session.get('identity', ''),
        'username': session.get('username', '')
    }
    return jsonify(user_info)

@app.route('/home')
def index():
    return render_template('Home.html')


@app.route('/Publish_exam')
def Publish_exam():
    '''发布考试（教师端）'''
    exams, pagination_info = _build_exam_view_models(include_pagination=True, page=1, per_page=10)
    class_options = [cls.class_name for cls in db.session.query(Class).order_by(Class.class_name).all()]
    exam_type_options = [value for value, in db.session.query(Exam.exam_type)
                         .filter(Exam.exam_type.isnot(None), Exam.exam_type != '')
                         .distinct()
                         .order_by(Exam.exam_type)]
    return render_template(
        'Publish_exam.html',
        exams=exams,
        pagination_info=pagination_info,
        class_options=class_options,
        exam_type_options=exam_type_options
    )



@app.route('/History_exam')
def History_exam():
    """渲染历史考试页面"""
    exam_type_options = [value for value, in db.session.query(Exam.exam_type)
    .filter(Exam.exam_type.isnot(None), Exam.exam_type != '')
    .distinct()
    .order_by(Exam.exam_type)]
    subject_type_options = [value for value, in db.session.query(Exam.subject)
    .filter(Exam.subject.isnot(None), Exam.subject != '')
    .distinct()
    .order_by(Exam.subject)]
    return render_template('History_exam.html',exam_type_options=exam_type_options,subject_type_options=subject_type_options)


@app.route('/api/exams/history')
def get_history_exams():
    """获取历史考试列表，支持筛选参数"""
    # 获取查询参数
    exam_type = request.args.get('exam_type', '')
    subject = request.args.get('subject', '')
    time_range = request.args.get('time_range', '')
    search = request.args.get('search', '').lower()
    page = int(request.args.get('page', 1))
    page_size = int(request.args.get('page_size', 10))

    # 构建查询（只查询已结束的考试）
    query = Exam.query.filter(Exam.status == '2')
    status_map = {
        0: "未开始",
        1: "进行中",
        2: "已结束",
        '0': "未开始",
        '1': "进行中",
        '2': "已结束"
    }

    # 类型筛选
    if exam_type:
        query = query.filter(Exam.exam_type == exam_type)

    # 学科筛选
    if subject:
        query = query.filter(Exam.subject == subject)

    # 时间范围筛选
    if time_range:
        now = datetime.now()

        if time_range == 'week':
            threshold = now - timedelta(days=7)
        elif time_range == 'month':
            threshold = now - timedelta(days=30)
        elif time_range == 'quarter':
            threshold = now - timedelta(days=90)
        elif time_range == 'semester':
            threshold = now - timedelta(days=180)
        else:
            threshold = datetime.min

        query = query.filter(Exam.end_time >= threshold)

    # 搜索功能 - 按考试名称和班级名称搜索
    if search:
        # 通过试卷名称搜索（Test2question替代原Test）
        matching_tests = Test2question.query.filter(Test2question.name.ilike(f'%{search}%')).all()
        test_ids = [test.id for test in matching_tests]

        # 通过班级名称搜索
        matching_classes = Class.query.filter(Class.class_name.ilike(f'%{search}%')).all()
        class_ids = [cls.id for cls in matching_classes]

        # 通过班级ID找到对应的考试ID
        exam_class_relations = ExamClass.query.filter(ExamClass.class_id.in_(class_ids)).all()
        exam_ids_from_classes = [ec.exam_id for ec in exam_class_relations]

        # 合并搜索条件：考试ID在匹配的试卷ID或班级相关的考试ID中
        all_matching_exam_ids = set(test_ids + exam_ids_from_classes)

        if all_matching_exam_ids:
            query = query.filter(Exam.id.in_(all_matching_exam_ids))
        else:
            # 如果没有匹配项，返回空结果
            query = query.filter(Exam.id == -1)

    # 执行查询并分页
    pagination = query.paginate(page=page, per_page=page_size)
    exams = pagination.items

    # 处理考试数据（补充试卷名称、班级信息、平均分）
    result = []
    for exam in exams:
        # 获取考试名称
        test = Exam.query.filter_by(id=exam.id).first()
        exam_name = test.name if test else f"考试_{exam.id}"

        # 获取参与班级名称
        exam_classes = ExamClass.query.filter_by(exam_id=exam.id).all()
        class_ids = [ec.class_id for ec in exam_classes]
        classes = Class.query.filter(Class.id.in_(class_ids)).all()
        class_names = ", ".join([cls.class_name for cls in classes])

        # 计算平均分（Answer表增加了question_id，需按考试ID分组）
        avg_score = db.session.query(func.avg(Answer.stu_score)).filter_by(exam_id=exam.id).scalar()
        avg_score = round(avg_score, 1) if avg_score else 0

        # 构建返回数据
        result.append({
            "id": exam.id,
            "name": exam_name,
            "exam_type": exam.exam_type,
            "subject": exam.subject,
            "class_ids": class_ids,
            "class_names": class_names,
            "start_time": exam.start_time.isoformat(),
            "end_time": exam.end_time.isoformat(),
            "exam_duration": exam.exam_duration,
            "student_count": exam.student_count,
            "status": status_map.get(exam.status, exam.status),
            "average_score": avg_score
        })

    return jsonify({
        'exams': result,
        'pagination': {
            'total': pagination.total,
            'page': page,
            'page_size': page_size,
            'pages': pagination.pages
        }
    })


@app.route('/api/exams/history/<int:exam_id>')
def get_exam_detail(exam_id):
    """获取单个历史考试详情"""
    exam = Exam.query.get(exam_id)
    status_map = {
        0: "未开始",
        1: "进行中",
        2: "已结束",
        '0': "未开始",
        '1': "进行中",
        '2': "已结束"
    }
    if not exam or exam.status != '2':
        return jsonify({'error': '考试不存在或未结束'}), 404

    # 获取试卷名称（关联Test2question表）
    test = Test2question.query.filter_by(id=exam.testpaper_id).first()
    exam_name = test.name if test else f"考试_{exam.id}"

    # 获取参与班级
    exam_classes = ExamClass.query.filter_by(exam_id=exam.id).all()
    class_ids = [ec.class_id for ec in exam_classes]
    classes = Class.query.filter(Class.id.in_(class_ids)).all()
    class_names = ", ".join([cls.class_name for cls in classes])

    # 计算平均分
    avg_score = db.session.query(func.avg(Answer.stu_score)).filter_by(exam_id=exam.id).scalar()
    avg_score = round(avg_score, 1) if avg_score else 0

    # 构建返回数据
    result = {
        "id": exam.id,
        "name": exam_name,
        "exam_type": exam.exam_type,
        "subject": exam.subject,
        "class_ids": class_ids,
        "class_names": class_names,
        "start_time": exam.start_time.isoformat(),
        "end_time": exam.end_time.isoformat(),
        "exam_duration": exam.exam_duration,
        "student_count": exam.student_count,
        "status": status_map.get(exam.status, exam.status),
        "average_score": avg_score,
        "teacher_id": exam.teacher_id
    }

    return jsonify(result)

@app.route('/api/exams/history/<int:exam_id>/questions')
def get_exam_questions(exam_id):
    """获取指定历史考试的试题"""
    # 验证考试是否存在且已结束
    exam = Exam.query.get(exam_id)
    if not exam or exam.status != '2':
        return jsonify({'error': '考试不存在或未结束'}), 404

    # 查询试题（Test_paper替代原ExamQuestion，通过testpaper_id关联）
    questions = Test_paper.query.filter_by(testpaper_id=exam.testpaper_id).all()
    result = []

    for q in questions:
        # 获取题库中的题目内容
        question_bank = QuestionBank.query.get(q.question_id)
        content = question_bank.title if question_bank else ""

        # 解析选项
        try:
            options = json.loads(q.option)
        except:
            options = q.option.split('|') if q.option else []

        result.append({
            "id": q.id,
            "type": q.type,
            "content": content,
            "options": options,
            "answer": q.answer,
            "score": q.score
        })

    return jsonify({
        'exam_id': exam_id,
        'questions': result
    })


@app.route('/api/exams/history/<int:exam_id>/stats')
def get_exam_stats(exam_id):
    """获取指定历史考试的统计数据"""
    # 验证考试是否存在
    exam = Exam.query.get(exam_id)
    if not exam or exam.status != '2':
        return jsonify({'error': '考试不存在或未结束'}), 404

    # 获取试卷名称
    test = Test2question.query.filter_by(id=exam.testpaper_id).first()
    exam_name = test.name if test else f"考试_{exam.id}"

    # 修改查询语句：按学生分组计算总分
    try:
        # 使用SQLAlchemy的group_by和sum函数
        student_scores = db.session.query(
            Answer.student_id,
            db.func.sum(Answer.stu_score).label('total_score')
        ).filter(
            Answer.exam_id == exam_id,
            Answer.stu_score.isnot(None)
        ).group_by(Answer.student_id).all()

        # 提取每个学生的总分
        scores = [score for student_id, score in student_scores if score is not None]

        print(f"找到 {len(scores)} 名学生的成绩")
        for student_id, score in student_scores:
            print(f"学生 {student_id} 的总分: {score}")

    except Exception as e:
        print(f"分组查询失败: {e}")
        # 如果分组查询失败，回退到原来的方法
        answers = Answer.query.filter_by(exam_id=exam_id).all()
        scores = [a.score for a in answers if a.score is not None]
        print(f"回退方法找到 {len(scores)} 条成绩记录")

    if not scores:
        return jsonify({'error': '暂无成绩数据'}), 404

    # 计算基本统计
    avg_score = round(sum(scores) / len(scores), 1)
    highest_score = max(scores)
    lowest_score = min(scores)

    # 计算分数分布
    distribution = [0, 0, 0, 0, 0]  # 0-60, 60-70, 70-80, 80-90, 90-100
    for score in scores:
        if score < 60:
            distribution[0] += 1
        elif score < 70:
            distribution[1] += 1
        elif score < 80:
            distribution[2] += 1
        elif score < 90:
            distribution[3] += 1
        else:
            distribution[4] += 1

    # 计算完成率
    total_students = exam.student_count
    completed_count = len(scores)  # 现在scores的长度就是完成考试的学生数
    completion_rate = round((completed_count / total_students) * 100, 1) if total_students > 0 else 0

    print(f"统计结果: 平均分={avg_score}, 最高分={highest_score}, 最低分={lowest_score}")
    print(f"分数分布: {distribution}")
    print(f"完成率: {completed_count}/{total_students} = {completion_rate}%")

    return jsonify({
        'exam_id': exam_id,
        'exam_name': exam_name,
        'total_students': total_students,
        'average_score': avg_score,
        'highest_score': highest_score,
        'lowest_score': lowest_score,
        'scores_distribution': {
            'ranges': ['0-60', '60-70', '70-80', '80-90', '90-100'],
            'counts': distribution
        },
        'completion_rate': completion_rate
    })


@app.route('/api/exams/history/<int:exam_id>', methods=['DELETE'])
def delete_exam(exam_id):
    """删除指定历史考试"""
    # 验证考试是否存在
    exam = Exam.query.get(exam_id)
    if not exam:
        return jsonify({'error': '考试不存在'}), 404

    try:
        # 获取关联的试卷ID
        testpaper_id = exam.testpaper_id

        # 删除关联数据（级联删除）
        # 1. 删除考试-班级关联
        ExamClass.query.filter_by(exam_id=exam_id).delete()

        # 2. 删除试题（Test_paper替代原ExamQuestion）
        Test_paper.query.filter_by(testpaper_id=testpaper_id).delete()

        # 3. 删除答案
        Answer.query.filter_by(exam_id=exam_id).delete()

        # 4. 删除试卷信息（Test2question替代原Test）
        Test2question.query.filter_by(id=testpaper_id).delete()

        # 5. 删除考试记录
        db.session.delete(exam)

        # 提交事务
        db.session.commit()
        return jsonify({'success': True, 'message': '考试已成功删除'})

    except Exception as e:
        db.session.rollback()
        return jsonify({'error': f'删除失败：{str(e)}'}), 500






@app.route('/Set_questions')
def Set_questions():
    '''一键出题'''
    result = None
    grades = Class.query.all()
    grade_set = []

    for grade in grades:
        grade_set.append(grade.grade)
    grade_set = set(grade_set)

    return render_template('Set_questions.html', result=result,grades = grade_set)

@app.route('/api/upload_exam', methods=['POST'])
def upload_exam_file():
    """上传试卷文件接口"""
    if 'file' not in request.files:
        return jsonify({'success': False, 'message': '没有选择文件'}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({'success': False, 'message': '没有选择文件'}), 400

    if file and allowed_exam_file(file.filename):
        # 生成安全的文件名
        original_filename = secure_filename(file.filename)
        file_ext = original_filename.rsplit('.', 1)[1].lower()
        unique_filename = f"{os.urandom(8).hex()}.{file_ext}"
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)

        # 保存文件
        file.save(file_path)

        # 解析试卷文件
        exam_info, message = exam_importer.parse_exam_file(file_path, original_filename)

        if exam_info:
            # 获取试卷详细内容
            exam_content = exam_importer.get_exam_content(file_path, file_ext)
            exam_info['content'] = exam_content

            return jsonify({
                'success': True,
                'message': message,
                'exam_info': exam_info
            })
        else:
            # 删除无效文件
            if os.path.exists(file_path):
                os.remove(file_path)
            return jsonify({'success': False, 'message': message}), 400
    else:
        return jsonify({'success': False, 'message': '请上传XML或JSON文件'}), 400


@app.route('/api/identify_questions', methods=['POST'])
def identify_questions():
    """智能识别试题API"""
    return api_identify_questions()


@app.route('/api/generate_exam', methods=['POST'])
def generate_exam():
    """生成试卷预览"""
    data = request.json
    exam_content = data.get('exam_content')

    if exam_content:
        print(exam_content)
        return jsonify({
            'success': True,
            'exam_preview': exam_content
        })
    else:
        return jsonify({'success': False, 'message': '没有试卷内容'}), 400

@app.route('/generate', methods=['POST'])
def generate():
    '''出题'''

    data = request.get_json()
    prompt = data.get('prompt', '')
    question_types = data.get('question_types', {})

    single_choice = question_types.get('single_choice', 0)
    multiple_choice = question_types.get('multiple_choice', 0)
    fill_blank = question_types.get('fill_blank', 0)
    short_answer = question_types.get('short_answer', 0)
    try:
        ai_response = ai_generate(prompt, single_choice, multiple_choice, fill_blank, short_answer)
        # 尝试解析JSON
        try:
            result_data = json.loads(ai_response)
        except json.JSONDecodeError:
            # 如果AI返回的不是标准JSON，创建一个错误提示
            result_data = {
                "选择题": [],
                "多选题": [],
                "填空题": [],
                "简答题": [],
                "error": "AI返回格式不正确，请重试"
            }

            # 返回JSON响应给前端
        return jsonify({
            'success': True,
            'data': result_data
        })
    except Exception as e:
        print("生成试题时出错:", str(e))
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/pdf_questions',methods=['GET','POST'])
def pdf_questions():
    '''pdf文件上传生成'''
    try:
        # 检查是否有文件
        if 'pdf_file' not in request.files:
            return jsonify({'error': '没有找到文件'}), 400

        file = request.files['pdf_file']

        # 检查文件是否选择
        if file.filename == '':
            return jsonify({'error': '未选择文件'}), 400

        # 检查文件类型
        if not allowed_file(file.filename):
            return jsonify({'error': '只允许上传PDF文件'}), 400

        # 安全处理文件名
        filename = secure_filename(file.filename)

        # 保存文件
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)

        single_choice = int(request.form['single_choice'])
        multiple_choice = int(request.form['multiple_choice'])
        fill_blank = int(request.form['fill_blank'])
        short_answer = int(request.form['short_answer'])


        try:
            result = pdf_q(file_path, single_choice, multiple_choice, fill_blank, short_answer)
            result = json.loads(result)
            return jsonify({'success': True,'data':result})

        except Exception as e:
            print('无法转换为JSON串，正在重新生成')
            result = pdf_q(file_path,single_choice,multiple_choice,fill_blank,short_answer)
            result = json.loads(result)

            return jsonify({'success': True,'data':result})
    except Exception as e:
        return jsonify({'error': f'上传失败: {str(e)}'}), 500

@app.route('/save_questions',methods=['GET','POST'])
def save_questions():
    '''保存题目到数据库'''
    try:
        # 检查请求内容类型
        content_type = request.headers.get('Content-Type', '')
        print(f"接收到请求，Content-Type: {content_type}")

        if 'application/json' in content_type:
            data = request.get_json()
            if data is None:
                return jsonify({'success': False, 'error': '无法解析JSON数据'}), 400
        else:
            return jsonify({
                'success': False,
                'error': f'不支持的Content-Type: {content_type}，请使用application/json'
            }), 400

        # 提取数据
        savedata = data.get('savedata')
        subject = data.get('subject')
        grade = data.get('grade')
        day = int(data.get('day'))
        type = data.get('type')

        print(f"接收到数据 - 科目: {subject}, 年级: {grade}, 天数: {day}，知识点{type}")
        print(f"题目数据: {savedata}")

        # 验证必要字段
        required_fields = ['savedata', 'subject', 'grade', 'day', 'type']
        missing_fields = [field for field in required_fields if not data.get(field)]

        if missing_fields:
            return jsonify({
                'success': False,
                'error': f'缺少必要字段: {", ".join(missing_fields)}'
            }), 400

        for key,value in savedata.items():
            for item in value:
                option_value = item.get('选项')
                if isinstance(option_value, dict):
                    # 将字典转换为字符串格式，例如: "A.选项内容 B.选项内容"
                    option_str = ' '.join([f"{k}.{v}" for k, v in option_value.items()])
                else:
                    option_str = option_value
                # 处理answer字段，如果是列表则转换为字符串
                answer_value = item['正确答案']
                if isinstance(answer_value, list):
                    answer_value = ','.join(answer_value)
                print(f"原始答案{option_value}")
                print(f"处理后的答案{option_str}")

                new_question = QuestionBank(
                    title = item['题目'],
                    option = option_str if key == '选择题' or key == '多选题' else None,
                    answer = answer_value,
                    grade = grade,
                    score = 1 if key == '选择题' else 2 if key == '多选题' else 1 if key == '填空题' else 5 if key == '简答题' else 0,
                    type = key,
                    day = day,
                    subject = subject,
                    knowledge = type
                )
                db.session.add(new_question)
            db.session.commit()

        return jsonify({
            'success': True,
            'message': '数据保存成功',
            'questions_count': len(savedata) if isinstance(savedata, list) else 0
        })

    except Exception as e:
        print(f"保存数据时出错: {str(e)}")
        import traceback
        traceback.print_exc()
        return jsonify({'success': False, 'error': str(e)}), 500

@app.route('/Waiting_exam')
def Waiting_exam():
    # 待考试(学生端)
    stu_id = session.get('username','')
    student = _get_current_student(stu_id)

    # 获取搜索参数
    exam_type_filter = request.args.get('exam_type', '').strip()
    subject_filter = request.args.get('subject', '').strip()
    keyword_filter = request.args.get('keyword', '').strip()

    exams = []
    if student and student.class_id:
        # 构建查询
        query = db.session.query(Exam)

        # 应用筛选条件
        if exam_type_filter and exam_type_filter != '全部类型':
            query = query.filter(Exam.exam_type == exam_type_filter)

        if subject_filter and subject_filter != '全部学科':
            query = query.filter(Exam.exam_subject == subject_filter)

        # 获取筛选后的考试记录
        exam_records = query.order_by(Exam.start_time.asc()).all()
        now = datetime.now()

        # 进一步应用关键字筛选
        if keyword_filter:
            keyword_lower = keyword_filter.lower()
            filtered_records = []
            for exam in exam_records:
                # 检查关键字是否匹配考试名称
                if keyword_lower in (exam.exam_name or '').lower():
                    filtered_records.append(exam)
                    continue

                # 检查关键字是否匹配学科
                if keyword_lower in (exam.exam_subject or '').lower():
                    filtered_records.append(exam)
                    continue

                # 检查关键字是否匹配考试类型
                if keyword_lower in (exam.exam_type or '').lower():
                    filtered_records.append(exam)
                    continue

            exam_records = filtered_records

        for exam in exam_records:
            # 使用单个class_id而不是class_ids
            if student.class_id != exam.class_id:
                continue
            exams.append(_serialize_exam_for_student(exam, now=now))

    return render_template('Waiting_exam.html', student=student, exams=exams,
                         exam_type_filter=exam_type_filter,
                         subject_filter=subject_filter,
                         keyword_filter=keyword_filter)


@app.route('/Question_Bank')
def Question_Bank():
    '''题库管理（教师端）'''
    return render_template('Question_Bank.html')


@app.route('/api/question_bank', methods=['GET'])
def get_question_bank():
    '''获取题库数据API'''
    try:
        # 获取查询参数
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 10, type=int)
        subject = request.args.get('subject', '')
        question_type = request.args.get('type', '')
        grade = request.args.get('grade', '')
        knowledge = request.args.get('knowledge', '')
        search_keyword = request.args.get('search', '')

        # 构建查询
        query = db.session.query(QuestionBank)

        # 添加过滤条件
        if subject:
            query = query.filter(QuestionBank.subject == subject)
        if question_type:
            query = query.filter(QuestionBank.type == question_type)
        if grade:
            query = query.filter(QuestionBank.grade == grade)
        if knowledge:
            query = query.filter(QuestionBank.knowledge.like(f'%{knowledge}%'))
        if search_keyword:
            query = query.filter(QuestionBank.title.like(f'%{search_keyword}%'))

        query=query.order_by(QuestionBank.id.desc())
        # 分页查询
        pagination = query.paginate(
            page=page,
            per_page=per_page,
            error_out=False
        )

        # 构建返回数据
        questions = []
        for question in pagination.items:
            questions.append({
                'id': question.id,
                'subject': question.subject,
                'title': question.title,
                'type': question.type,
                'grade': question.grade,
                'score': question.score,
                'day': question.day,
                'knowledge': question.knowledge,
                'option': question.option,
                'answer': question.answer
            })

        return jsonify({
            'success': True,
            'data': {
                'questions': questions,
                'pagination': {
                    'page': page,
                    'per_page': per_page,
                    'total': pagination.total,
                    'pages': pagination.pages
                }
            }
        })

    except Exception as e:
        print(f"获取题库数据时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取数据失败'
        }), 500


@app.route('/api/question_bank/<int:question_id>', methods=['GET', 'PUT'])
def handle_question(question_id):
    '''获取或更新题目'''
    try:
        question = db.session.query(QuestionBank).get(question_id)
        if not question:
            return jsonify({'success': False, 'error': '题目不存在'}), 404

        if request.method == 'GET':
            # 获取题目详情
            return jsonify({
                'success': True,
                'data': {
                    'id': question.id,
                    'subject': question.subject,
                    'title': question.title,
                    'type': question.type,
                    'grade': question.grade,
                    'score': question.score,
                    'day': question.day,
                    'knowledge': question.knowledge,
                    'option': question.option,
                    'answer': question.answer
                }
            })

        elif request.method == 'PUT':
            # 更新题目
            data = request.get_json()

            # 更新字段
            update_fields = ['title', 'subject', 'type', 'grade', 'score', 'day', 'knowledge', 'option', 'answer']
            for field in update_fields:
                if field in data:
                    setattr(question, field, data[field])

            db.session.commit()

            return jsonify({
                'success': True,
                'message': '更新成功'
            })
        return None

    except Exception as e:
        db.session.rollback()
        print(f"处理题目时出错: {str(e)}")
        return jsonify({'success': False, 'error': '操作失败'}), 500
@app.route('/api/question_bank/<int:question_id>', methods=['DELETE'])
def delete_question(question_id):
    '''删除题目API'''
    try:
        question = db.session.query(QuestionBank).get(question_id)
        if not question:
            return jsonify({
                'success': False,
                'error': '题目不存在'
            }), 404

        db.session.delete(question)
        db.session.commit()

        return jsonify({
            'success': True,
            'message': '删除成功'
        })

    except Exception as e:
        db.session.rollback()
        print(f"删除题目时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '删除失败'
        }), 500




@app.route('/api/question_bank/filters', methods=['GET'])
def get_filters():
    '''获取筛选条件选项'''
    try:
        # 获取所有学科
        subjects = db.session.query(QuestionBank.subject).distinct().all()
        subjects = [s[0] for s in subjects if s[0]]

        # 获取所有题型
        types = db.session.query(QuestionBank.type).distinct().all()
        types = [t[0] for t in types if t[0]]

        # 获取所有年级
        grades = db.session.query(QuestionBank.grade).distinct().all()
        grades = [g[0] for g in grades if g[0]]

        # 获取所有知识点
        knowledges=db.session.query(QuestionBank.knowledge).distinct().all()
        knowledges=[k[0] for k in knowledges if k[0]]

        return jsonify({
            'success': True,
            'data': {
                'subjects': subjects,
                'types': types,
                'grades': grades,
                'knowledges': knowledges
            }
        })

    except Exception as e:
        print(f"获取筛选条件时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取筛选条件失败'
        }), 500


@app.route('/stu_management')
def Stu_management():
    '''学生管理（教师端）'''
    return render_template('stu_management.html')

@app.route('/class_management')
def Class_management():
    '''班级管理（教师端）'''
    return render_template('class_management.html')

@app.route('/class_all',methods=['GET','POST'])
def class_all():
    '''查找所有班级'''
    try:
        teacher = db.session.query(Teacher).all()
        teacher_map = {t.id: t.name for t in teacher}

        classes = db.session.query(Class).all()
        result = []
        for cls in classes:
            stu_num = db.session.query(Student).filter(Student.class_id == cls.id).count()
            teacher_name = teacher_map.get(cls.teacher_id, '未知教师')
            result.append({
                'id': cls.id,
                'grade': cls.grade,
                'class_name': cls.class_name,
                'status': cls.status,
                'create_date': cls.create_date,
                'teacher_name': teacher_name,
                'stu_num': stu_num
            })
        return jsonify({'success': True, 'data': result})

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500


@app.route('/class_select',methods=['GET','POST'])
def class_select():
    '''搜索班级'''
    try:
        data = request.get_json()
        keyword = data.get('keyword')
        teacher = db.session.query(Teacher).all()
        teacher_map = {t.id: t.name for t in teacher}

        teacher_id = db.session.query(Teacher).filter(Teacher.name.like(f'%{keyword}%')).all()

        if teacher_id is not None:
            teacher_ids = [tea.id for tea in teacher_id]
            classes = db.session.query(Class).filter(or_(
                Class.grade.like(f'%{keyword}%'),
                Class.class_name.like(f'%{keyword}%'),
                Class.teacher_id.in_(teacher_ids)
            ))
        else:
            classes = db.session.query(Class).filter(or_(
                Class.grade.like(f'%{keyword}%'),
                Class.class_name.like(f'%{keyword}%')
            ))

        result = []
        for cls in classes:
            stu_num = db.session.query(Student).filter(Student.class_id == cls.id).count()
            teacher_name = teacher_map.get(cls.teacher_id, '未知教师')
            result.append({
                'id': cls.id,
                'grade': cls.grade,
                'class_name': cls.class_name,
                'status': cls.status,
                'create_date': cls.create_date,
                'teacher_name': teacher_name,
                'stu_num': stu_num
            })
        return jsonify({'success': True, 'data': result})

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500

@app.route('/class_option',methods=['GET','POST'])
def class_option():
    '''根据状态查找班级'''
    try:
        data = request.get_json()
        selectedStatus = data.get('selectedStatus')
        teacher = db.session.query(Teacher).all()
        teacher_map = {t.id: t.name for t in teacher}

        if selectedStatus == '0':
            classes = db.session.query(Class).filter().all()
        elif selectedStatus == '1':
            classes = db.session.query(Class).filter(Class.status == '正常').all()
        elif selectedStatus == '2':
            classes = db.session.query(Class).filter(Class.status == '已毕业').all()
        result = []
        for cls in classes:
            stu_num = db.session.query(Student).filter(Student.class_id == cls.id).count()
            teacher_name = teacher_map.get(cls.teacher_id, '未知教师')
            result.append({
                'id': cls.id,
                'grade': cls.grade,
                'class_name': cls.class_name,
                'status': cls.status,
                'create_date': cls.create_date,
                'teacher_name': teacher_name,
                'stu_num': stu_num
            })
        return jsonify({'success': True, 'data': result})

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500

@app.route('/deleteClass/<int:class_id>',methods=['GET','POST','DELETE'])
def deleteClass(class_id):
    '''删除班级'''
    try:
        # 查找班级
        class_to_delete = db.session.query(Class).get(class_id)

        if not class_to_delete:
            return jsonify({
                'success': False,
                'error': '班级不存在'
            }), 404

        # 检查是否有学生关联
        student_count = db.session.query(Student).filter(Student.class_id == class_id).count()
        if student_count > 0:
            return jsonify({
                'success': False,
                'error': f'该班级还有 {student_count} 名学生，无法删除'
            }), 400

        # 删除班级
        db.session.delete(class_to_delete)
        db.session.commit()

        return jsonify({
            'success': True,
            'message': '班级删除成功'
        })

    except Exception as e:
        db.session.rollback()
        print(f"删除班级错误: {str(e)}")
        return jsonify({
            'success': False,
            'error': '删除失败，请稍后重试'
        }), 500

@app.route('/updateClass/<int:class_id>',methods=['GET','POST','PUT'])
def updateClass(class_id):
    '''修改班级'''
    try:
        class_to_update = db.session.query(Class).filter(Class.id == class_id).first()
        if not class_to_update:
            return jsonify({'success':False, 'error':'班级不存在'}), 404
        class_data = request.get_json()
        class_name = class_data['class_name']
        grade = class_data['grade']
        teacher_name = class_data['teacher_name']
        status = class_data['status']

        class_name_old = db.session.query(Class).filter(and_(Class.class_name == class_name,Class.status == '正常')).all()
        if len(class_name_old) > 0:
            return jsonify({'success': False, 'error': '班级名称已存在'}), 400

        teacher_id = db.session.query(Teacher).filter(Teacher.name == teacher_name).first().id
        if not teacher_id:
            return jsonify({'success':False, 'error':'该教师不存在'}), 404

        class_to_update.class_name = class_name
        class_to_update.grade = grade
        class_to_update.teacher_name = teacher_name
        class_to_update.status = status

        db.session.commit()
        return jsonify({'success':True})


    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500

@app.route('/addClass',methods=['GET','POST'])
def addClass():
    '''添加班级'''
    try:
        data = request.get_json()
        class_name = data['class_name']
        teacher_name = data['teacher_name']
        grade = data['grade']
        create_date = data['create_date']
        status = data['status']

        class_old = db.session.query(Class).filter(Class.class_name == class_name).first()
        if class_old is not None:
            return jsonify({'success': False, 'error': '班级名称重复'}), 400
        teacher_id = db.session.query(Teacher).filter(Teacher.name == teacher_name).first()
        if teacher_id is None:
            return jsonify({'success': False, 'error': '该教师不存在'}), 400

        new_class = Class(class_name=class_name,grade=grade,create_date=create_date,status=status,teacher_id=teacher_id.id)
        db.session.add(new_class)
        db.session.commit()
        return jsonify({'success': True})

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500


@app.route('/Exam_record')
def Exam_record():
    '''个人考试记录（学生端）'''
    return render_template('Exam_record.html')



@app.route('/Mistake_question')
def Mistake_question():
    '''错题本'''
    num = Answer.query.filter(Answer.num > 0).count()
    return render_template('Mistake_question.html',num = num)

@app.route('/new_question/<int:stu_id>',methods=['GET','POST'])
def new_question(stu_id):
    '''随机一道题'''
    try:
        question_id = Answer.query.filter(and_(Answer.student_id == stu_id,Answer.num > 0)).order_by(func.random()).first()
        question = QuestionBank.query.filter(QuestionBank.id == question_id.question_id).first()
        if question is None:
            return jsonify({'success': False, 'error': '题目未找到'}), 404
        try:
            print(question.option)
            pattern = r'([A-Z])\.\s*([^A-Z]+?)(?=\s+[A-Z]\.|$)'
            matches = re.findall(pattern, question.option)

            option_dict = {}
            for letter, content in matches:
                option_dict[letter] = content
            option_json = json.dumps(option_dict, ensure_ascii=False)
        except:
            # 异常处理：默认空字典
            option_json = "{}"
        question_data = {
            'id': question.id,
            'type': question.type,
            'title': question.title,
            'option': option_json,
            'source': question.score,
            'exam_id': question_id.exam_id,
        }
        return jsonify({'success': True, 'data': question_data})
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500

@app.route('/submit_answer',methods=['GET','POST'])
def submit_answer():
    '''ai对用户提交的答案进行打分'''
    try:
        data = request.get_json()
        question_id = data['question_id']
        student_id = data['student_id']
        student_answer = data['answer']
        exam_id = data['exam_id']

        question = QuestionBank.query.filter(QuestionBank.id == question_id).first()
        score = question.score
        answer = question.answer
        type = question.type

        student_score = scoring(score, student_answer, answer, type)

        if student_score is None:
            return jsonify({'success': False, 'error': '打分失败'}), 404

        stu2qes = Answer.query.filter(and_(Answer.student_id == student_id,Answer.question_id == question_id,Answer.exam_id == exam_id)).first()
        try:
            if int(float(student_score)) >= int(score):
                stu2qes.num -= 1
                db.session.commit()
            else:
                stu2qes.num = 2
                db.session.commit()
        except Exception as e:
            return jsonify({'success': False, 'error': str(e)}), 500
        data = {
            'student_score': student_score,
            'score': score,
            'correct_answer': answer
        }
        return jsonify({'success': True, 'data': data})

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 404

#创建试卷要用到的，获取该试卷的id和班级id
@app.route('/create_exam_schedule')
def create_exam_schedule_page():
    from flask import session

    # 从session中获取testpaper_id
    testpaper_id = session.get('testpaper_id')
    if not testpaper_id:
        # 如果没有testpaper_id，重定向到创建考试页面
        return redirect(url_for('create_exambp.create_exams'))

    # 从数据库中获取班级选项
    classes = db.session.query(Class).all()
    class_options = [cls.class_name for cls in classes]

    return render_template('create_exam_schedule.html', testpaper_id=testpaper_id, class_options=class_options)

@app.route('/api/students', methods=['GET', 'POST'])
def students_api():
    if request.method == 'GET':
        keyword = (request.args.get('keyword') or '').strip()
        gender = (request.args.get('gender') or '').strip()
        class_id = (request.args.get('class_id') or '').strip()

        base_query = db.session.query(Student)

        class_records = db.session.query(Class).order_by(Class.class_name).all()
        class_map = {str(cls.id): cls.class_name for cls in class_records}
        genders = [
            value for value, in db.session.query(Student.gender)
            .filter(Student.gender.isnot(None), Student.gender != '')
            .distinct()
        ]

        if keyword:
            like_pattern = f"%{keyword}%"
            base_query = base_query.filter(
                or_(
                    Student.id.like(like_pattern),
                    Student.name.like(like_pattern),
                    Student.class_id.like(like_pattern),
                    Student.account.like(like_pattern)
                )
            )
        if gender:
            base_query = base_query.filter(Student.gender == gender)
        if class_id:
            base_query = base_query.filter(Student.class_id == class_id)

        students = base_query.order_by(Student.id).all()
        student_dicts = []
        for student in students:
            data = {
                'id': student.id,
                'name': student.name,
                'age': student.age,
                'gender': student.gender,
                'class_id': student.class_id
            }
            class_key = str(student.class_id) if student.class_id is not None else None
            data['class_name'] = class_map.get(class_key)
            student_dicts.append(data)

        class_options = [{'id': str(cls.id), 'name': cls.class_name} for cls in class_records]

        return jsonify({
            'students': student_dicts,
            'meta': {
                'classes': class_options,
                'genders': genders
            }
        })

    data = request.get_json() or {}
    student_id = (data.get('student_id') or '').strip()
    name = (data.get('name') or '').strip()
    if not student_id or not name:
        return jsonify({'message': '学号和姓名不能为空'}), 400

    if db.session.query(Student).get(student_id):
        return jsonify({'message': '学号已存在'}), 400

    age_raw = data.get('age')
    if age_raw in (None, ''):
        age = None
    else:
        try:
            age = int(age_raw)
            if age < 0:
                raise ValueError
        except (TypeError, ValueError):
            return jsonify({'message': '年龄必须是非负整数'}), 400

    class_input = (data.get('class_name') or data.get('class_id') or '').strip()
    class_id_value = None
    if class_input:
        class_record = db.session.query(Class).filter(Class.class_name == class_input).first()
        if not class_record:
            try:
                class_record = db.session.query(Class).get(int(class_input))
            except (TypeError, ValueError):
                class_record = None
        if not class_record:
            return jsonify({'message': f'班级"{class_input}"不存在'}), 400
        class_id_value = str(class_record.id)

    student = Student(
        id=student_id,
        name=name,
        age=age,
        gender=(data.get('gender') or '').strip() or '未知',
        class_id=class_id_value,
        password=(data.get('password') or '').strip()
    )

    db.session.add(student)
    db.session.commit()
    return jsonify({'student': {'id': student.id, 'name': student.name, 'age': student.age, 'gender': student.gender, 'class_id': student.class_id}}), 201

@app.route('/api/students/<student_id>', methods=['PUT', 'DELETE'])
def student_detail_api(student_id):
    student = db.session.query(Student).get(student_id)
    if not student:
        return jsonify({'message': '学生不存在'}), 404

    if request.method == 'DELETE':
        # 删除该学生的所有答案记录
        Answer.query.filter_by(student_id=student.id).delete()
        # 删除学生记录
        db.session.delete(student)
        db.session.commit()
        return jsonify({'message': '已删除'})

    data = request.get_json() or {}

    name = data.get('name')
    if name is not None:
        name = name.strip()
        if not name:
            return jsonify({'message': '姓名不能为空'}), 400
        student.name = name

    if 'age' in data:
        age_raw = data.get('age')
        if age_raw in (None, ''):
            student.age = None
        else:
            try:
                age_value = int(age_raw)
                if age_value < 0:
                    raise ValueError
                student.age = age_value
            except (TypeError, ValueError):
                return jsonify({'message': '年龄必须是非负整数'}), 400

    if 'gender' in data:
        gender = (data.get('gender') or '').strip()
        student.gender = gender or None

    if 'class_name' in data or 'class_id' in data:
        class_input = (data.get('class_name') or data.get('class_id') or '').strip()
        if class_input:
            class_record = db.session.query(Class).filter(Class.class_name == class_input).first()
            if not class_record:
                try:
                    class_record = db.session.query(Class).get(int(class_input))
                except (TypeError, ValueError):
                    class_record = None
            if not class_record:
                return jsonify({'message': f'班级"{class_input}"不存在'}), 400
            student.class_id = str(class_record.id)
        else:
            student.class_id = None

    if 'account' in data:
        account = (data.get('account') or '').strip()
        student.account = account or None

    if 'password' in data:
        password = (data.get('password') or '').strip()
        student.password = password

    db.session.commit()
    return jsonify({
        'student': {
            'id': student.id,
            'name': student.name,
            'age': student.age,
            'gender': student.gender,
            'class_id': student.class_id,
            'account': student.account
        }
    })

@app.route('/api/exam_schedules/<int:exam_id>', methods=['DELETE'])
def delete_exam_schedule(exam_id):
    """删除考试"""
    try:
        exam = db.session.query(Exam).get(exam_id)
        if not exam:
            return jsonify({'error': '考试不存在'}), 404

        db.session.delete(exam)
        db.session.commit()
        return jsonify({'success': True, 'message': '考试已删除'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

def _build_exam_view_models(status_filter=None, exam_type_filter=None, class_name_filter=None, keyword_filter=None, page=None, per_page=None, include_pagination=False):
    class_records = db.session.query(Class).order_by(Class.class_name).all()
    class_map = {cls.id: cls.class_name for cls in class_records}
    class_name_to_id = {cls.class_name: cls.id for cls in class_records}
    teacher_map = {teacher.id: teacher.name for teacher in db.session.query(Teacher)
    .all()}
    testpaper_map = {paper.id: paper.name for paper in db.session.query(Test2question).all()}
    status_styles = {
        '0': ('未开始', 'bg-status-pending/20 text-status-pending'),
        '1': ('进行中', 'bg-status-active/20 text-status-active'),
        '2': ('已结束', 'bg-status-expired/20 text-status-expired')
    }

    query = db.session.query(Exam)
    if status_filter is not None:
        query = query.filter(Exam.status == status_filter)
    if exam_type_filter:
        query = query.filter(Exam.exam_type == exam_type_filter)

    exams = []
    keyword_lower = (keyword_filter or '').strip().lower()
    target_class_id = None
    if class_name_filter:
        target_class_id = class_name_to_id.get(class_name_filter.strip())

    base_query = query.order_by(Exam.start_time.desc())
    pagination = None
    if include_pagination:
        try:
            current_page = int(page or 1)
        except (TypeError, ValueError):
            current_page = 1
        if current_page < 1:
            current_page = 1
        try:
            page_size = int(per_page or 10)
        except (TypeError, ValueError):
            page_size = 10
        if page_size < 1:
            page_size = 1
        if page_size > 100:
            page_size = 100
        pagination = base_query.paginate(page=current_page, per_page=page_size, error_out=False)
        exam_records = pagination.items
    else:
        exam_records = base_query.all()

    for exam in exam_records:
        try:
            # 使用class_id而不是class_ids
            class_ids = [exam.class_id] if exam.class_id else []
        except (TypeError, ValueError):
            class_ids = []
            for raw in str(exam.class_id or '').split(','):
                raw = raw.strip()
                if not raw:
                    continue
                try:
                    class_ids.append(int(raw))
                except ValueError:
                    continue

        if isinstance(class_ids, (int, str)):
            try:
                class_ids = [int(class_ids)]
            except (TypeError, ValueError):
                class_ids = [class_ids]
        elif not isinstance(class_ids, list):
            class_ids = list(class_ids)

        class_id_set = {cid for cid in class_ids if isinstance(cid, int)}
        if target_class_id is not None and target_class_id not in class_id_set:
            continue

        class_names = [class_map.get(cid, str(cid)) for cid in class_ids]
        # 将状态字符串映射到数字索引
        # status_map = {'未开始': 0, '进行中': 1, '已结束': 2}
        # status_index = status_map.get(exam.status, 0)
        status_index = exam.status
        status_label, status_class = status_styles.get(status_index, ('未开始', 'bg-status-pending/20 text-status-pending'))
        start_text = exam.start_time.strftime('%Y-%m-%d %H:%M') if exam.start_time else ''
        end_text = exam.end_time.strftime('%Y-%m-%d %H:%M') if exam.end_time else ''

        teacher_name = teacher_map.get(exam.teacher_id, '未知教师')
        testpaper_name = testpaper_map.get(exam.testpaper_id, '未知试卷')

        if keyword_lower:
            combined = ' '.join([
                exam.name or '',
                exam.subject or '',
                teacher_name or '',
                testpaper_name or ''
            ]).lower()
            if keyword_lower not in combined:
                continue

        exams.append({
            'id': exam.id,
            'name': exam.name,
            'subject': exam.subject,
            'class_names': class_names,
            'start_time': start_text,
            'end_time': end_text,
            'time_range': f'{start_text} - {end_text}' if start_text and end_text else '',
            'duration': exam.exam_duration,
            'exam_type': exam.exam_type,
            'headcount': exam.student_count,
            'teacher_name': teacher_name,
            'testpaper_name': testpaper_name,
            'status_label': status_label,
            'status_class': status_class
        })

    if include_pagination and pagination is not None:
        return exams, {
            'page': pagination.page,
            'per_page': pagination.per_page,
            'total': pagination.total,
            'pages': pagination.pages,
            'has_next': pagination.has_next,
            'has_prev': pagination.has_prev
        }
    return exams

def _parse_class_ids(raw_value):
    if raw_value is None:
        return set()
    try:
        parsed = json.loads(raw_value)
    except (TypeError, ValueError):
        parsed = [item.strip() for item in str(raw_value).split(',') if item.strip()]

    if isinstance(parsed, (int, str)):
        parsed = [parsed]
    elif not isinstance(parsed, list):
        parsed = list(parsed)

    return {str(item) for item in parsed}


import re


def _parse_options(option_string):
    """
    从混杂的字符串中解析出干净的选项列表。
    支持多种格式的选项解析，包括：
    - 单标签："A. 10 + 5 B. 12 + 3"
    - 含特殊字符："A.pd.DataFrame() B.pd.Series()"
    - 双重标签："A.A. f(x) = x³ B.B. f(x) = x²"
    - 中文标点："a、选项一 b、选项二"
    """
    if not isinstance(option_string, str) or not option_string.strip():
        return []

    # 增强版正则表达式，更精准匹配选项标签
    # 匹配规则：大写字母 + (点或中文顿号) + 可选空格 + 内容，直到下一个选项标签或结束
    pattern = re.compile(r'([A-Z])[.、]\s*(.*?)(?=\s+[A-Z][.、]|$)', re.DOTALL)
    matches = pattern.findall(option_string)

    options = []
    for label, content in matches:
        content = content.strip()
        if content:
            # 处理双重标签中的重复标签（如"A.A...."中的第二个A.）
            if len(content) > 0 and content[0].upper() == label and content[1] in ['.', '、']:
                content = content[2:].strip()
            options.append({
                'label': label,
                'value': label,
                'content': content
            })

    return options


def _normalize_options(parsed_options):
    """
    规范化选项列表。如果输入已经是标准格式，则直接返回。
    """
    # 检查输入是否已经是标准格式 [{'label': 'A', 'value': 'A', 'content': '...'}]
    if isinstance(parsed_options, list) and parsed_options and isinstance(parsed_options[0], dict) and 'label' in \
            parsed_options[0]:
        return parsed_options

    # 如果不是，说明数据格式异常，返回空列表
    return []

def _determine_render_type(question_type, options):
    type_text = (question_type or '').lower()

    if any(keyword in type_text for keyword in ['填空', 'fill', '空格']):
        return 'text'
    if any(keyword in type_text for keyword in ['简答', '问答', '解答', '说明', 'short']):
        return 'textarea'
    if any(keyword in type_text for keyword in ['多选', 'multiple']):
        return 'multiple'
    if any(keyword in type_text for keyword in ['单选', '选择', '判断', 'true/false', '单项']) and options:
        return 'single'

    if options:
        return 'single'
    return 'text'

def _get_current_student(default_student_id):
    student_id = session.get('student_id')
    if student_id is None:
        student = db.session.query(Student).filter_by(id=default_student_id).first()
        if student:
            session['student_id'] = student.id
        return student
    return db.session.query(Student).filter_by(id=student_id).first()

def _serialize_exam_for_student(exam, now=None):
    now = now or datetime.now()
    status_styles = {
        0: ('未开始', 'bg-red-100 text-red-600'),
        1: ('进行中', 'bg-green-100 text-green-600'),
        2: ('已结束', 'bg-gray-200 text-gray-600')
    }

    exam_progress = session.get('exam_progress', {})
    progress_status = exam_progress.get(str(exam.id))

    try:
        status_value = int(exam.status)
    except (TypeError, ValueError):
        status_value = 0

    status_label, status_badge_class = status_styles.get(status_value, ('未开始', 'bg-red-100 text-red-600'))
    display_text = status_label

    within_time_window = False

    if exam.start_time and now < exam.start_time:
        delta = exam.start_time - now
        total_minutes = int(delta.total_seconds() // 60)
        days, remainder_minutes = divmod(total_minutes, 1440)
        hours, minutes = divmod(remainder_minutes, 60)
        parts = []
        if days:
            parts.append(f"{days}天")
        if hours:
            parts.append(f"{hours}小时")
        if minutes and not days:
            parts.append(f"{minutes}分钟")
        if not parts:
            parts.append('不到1分钟')
        display_text = ''.join(parts) + '后开始'
        status_badge_class = 'bg-red-100 text-red-600'
    elif exam.end_time and now > exam.end_time:
        display_text = '考试已结束'
        status_badge_class = 'bg-gray-200 text-gray-600'
    elif exam.start_time and exam.end_time and exam.start_time <= now <= exam.end_time:
        display_text = '考试进行中'
        status_badge_class = 'bg-green-100 text-green-600'
        within_time_window = True

    has_started = progress_status == 'in_progress'
    can_start = status_value != 2 and (within_time_window or status_value == 0)
    is_in_progress = has_started or (status_value == 1 and within_time_window)

    return {
        'id': exam.id,
        'exam_name': exam.name,
        'exam_type': exam.exam_type,
        'subject': exam.subject,
        'start_time_text': exam.start_time.strftime('%Y-%m-%d %H:%M') if exam.start_time else '',
        'end_time_text': exam.end_time.strftime('%Y-%m-%d %H:%M') if exam.end_time else '',
        'duration_text': f"{exam.exam_duration}分钟" if exam.exam_duration else '',
        'status_display': display_text,
        'status_badge_class': status_badge_class,
        'can_start': can_start,
        'is_in_progress': is_in_progress,
        'progress_status': progress_status,
        'start_url': url_for('take_exam', exam_id=exam.id)
    }

def _load_exam_questions(exam):
    question_rows = (
        db.session.query(Test_paper, QuestionBank)
        .outerjoin(QuestionBank, Test_paper.question_id == QuestionBank.id)
        .filter(Test_paper.testpaper_id == exam.testpaper_id)
        .order_by(Test_paper.id.asc())
        .all()
    )

    serialized = []
    for detail, question in question_rows:
        question_text = question.title if question else detail.question_id
        option_payload = detail.option or (question.option if question else None)
        parsed_options = _parse_options(option_payload)
        normalized_options = _normalize_options(parsed_options)

        question_type = detail.type or (question.type if question else '')
        render_type = _determine_render_type(question_type, normalized_options)
        if render_type in ('text', 'textarea'):
            normalized_options = []
        elif render_type == 'multiple':
            if not normalized_options:
                render_type = 'text'

        serialized.append({
            'detail_id': detail.id,
            'question_id': detail.question_id,
            'question': question_text,
            'type': question_type,
            'options': normalized_options,
            'render_type': render_type,
            'score': detail.score,
            'answer': detail.answer,
        })

    return serialized

@app.route('/api/exam_schedules/<int:exam_id>/start', methods=['POST'])
def prepare_exam(exam_id):
    student = _get_current_student()
    if not student:
        return jsonify({'success': False, 'message': '学生不存在或未登录'}), 404

    exam = Exam.query.get(exam_id)
    if not exam:
        return jsonify({'success': False, 'message': '考试不存在'}), 404

    # 使用单个class_id而不是class_ids
    if student.class_id != exam.class_id:
        return jsonify({'success': False, 'message': '您没有权限参加此考试'}), 403

    now = datetime.now()
    if exam.start_time and now < exam.start_time:
        return jsonify({'success': False, 'message': '考试尚未开始'}), 400
    if exam.end_time and now > exam.end_time:
        return jsonify({'success': False, 'message': '考试已结束'}), 400

    # 检查试卷是否存在
    if not exam.testpaper_id:
        return jsonify({'success': False, 'message': '未找到关联的试卷'}), 404

    # 检查试卷题目是否存在
    test_paper = Test_paper.query.filter_by(testpaper_id=exam.testpaper_id).first()
    if not test_paper:
        return jsonify({'success': False, 'message': '未找到试卷题目'}), 404

    # 只存储必要信息到session，不再存储题目数据
    session['current_exam'] = {
        'exam_id': exam.id,
        'testpaper_id': exam.testpaper_id,
        'student_id': student.id,
        'start_time': now.isoformat(),
        'end_time': exam.end_time.isoformat() if exam.end_time else None
    }

    exam_progress = session.get('exam_progress', {})
    exam_progress[str(exam.id)] = 'in_progress'
    session['exam_progress'] = exam_progress

    return jsonify({'success': True, 'redirect_url': url_for('take_exam', exam_id=exam.id)})

@app.route('/take_exam/<int:exam_id>')
def take_exam(exam_id):
    student = _get_current_student()
    if not student:
        return redirect(url_for('Waiting_exam'))

    # 检查考试是否存在
    exam = Exam.query.get(exam_id)
    if not exam:
        return redirect(url_for('Waiting_exam'))

    now = datetime.now()
    if exam.end_time and now > exam.end_time:
        return redirect(url_for('Waiting_exam'))

    remaining_seconds = None
    if exam.end_time:
        remaining = exam.end_time - now
        remaining_seconds = max(int(remaining.total_seconds()), 0)

    # 根据试卷ID从试卷表获取题目信息
    question_rows = (
        db.session.query(Test_paper, QuestionBank)
        .outerjoin(QuestionBank, Test_paper.question_id == QuestionBank.id)
        .filter(Test_paper.testpaper_id == exam.testpaper_id)
        .order_by(Test_paper.id.asc())
        .all()
    )


    # 处理题目数据
    processed_questions = []
    for detail, question in question_rows:
        # 获取题目文本，优先使用QuestionBank表中的title
        question_text = question.title if question else detail.question_id

        # 获取选项，优先使用Test_paper表中的选项
        option_payload = detail.option or (question.option if question else None)
        final_options = _parse_options(option_payload)

        # 获取题目类型，优先使用Test_paper表中的类型
        question_type = detail.type or (question.type if question else '')

        # 根据题目类型判断渲染类型
        render_type = 'single'  # 默认单选
        if question_type == '多选题':
            render_type = 'multiple'
        elif question_type == '填空题':
            render_type = 'text'
        elif question_type == '简答题':
            render_type = 'textarea'


        processed_questions.append({
            'question_id': detail.question_id,  # 使用Test_paper表中的ID
            'detail_id': detail.id,    # 保留detail_id以便提交答案时使用
            'render_type': render_type,  # 设置渲染类型
            'type': question_type,
            'question': question_text,
            'options': final_options,  # 使用处理后的选项
            'score': detail.score,  # 使用Test_paper表中的分值
            'answer': detail.answer  # 使用Test_paper表中的答案
        })
        print(option_payload)
        print('********')
        print(f"最终选项: {final_options}")


    return render_template(
        'Exam_take.html',
        exam=exam,
        student=student,
        questions=processed_questions,  # 传递处理后的数据
        remaining_seconds=remaining_seconds
    )


@app.route('/save_exam_answer/<int:exam_id>', methods=['POST'])
def save_exam_answer(exam_id):
    """保存考试答案（不提交）"""
    # student = _get_current_student()
    student = Student.query.get(1)
    if not student:
        return jsonify({'success': False, 'message': '学生不存在或未登录'}), 404

    # 检查考试是否存在
    exam = Exam.query.get(exam_id)
    if not exam:
        return jsonify({'success': False, 'message': '考试不存在'}), 404

    payload = request.get_json() or {}
    submitted_answers = payload.get('answers', [])

    # 将提交的答案转换为方便查找的字典，键为题库ID (question_id)
    submitted_answer_map = {str(item['question_id']): item.get('answer') for item in submitted_answers if 'question_id' in item}

    student_id_value = int(student.id) if isinstance(student.id, str) and student.id.isdigit() else student.id

    try:
        # 删除旧草稿
        Answer.query.filter_by(exam_id=exam_id, student_id=student_id_value).delete()

        # 获取试卷的所有题目，确保按顺序处理
        test_paper_records = Test_paper.query.filter_by(
            testpaper_id=exam.testpaper_id
        ).order_by(Test_paper.id).all()

        # 添加新草稿
        answer_records_to_add = []

        for test_paper in test_paper_records:
            question_id = test_paper.question_id
            question_id_str = str(question_id)
            submitted_answer = submitted_answer_map.get(question_id_str)

            # 无论学生是否提交答案，都创建记录
            # 确保答案格式一致，如果已经是字符串则直接使用，否则转换为JSON
            if submitted_answer is None:
                processed_answer = json.dumps("")
            elif isinstance(submitted_answer, str):
                processed_answer = submitted_answer
            else:
                processed_answer = json.dumps(submitted_answer)

            answer_records_to_add.append(
                Answer(
                    exam_id=exam_id,
                    student_id=student_id_value,
                    question_id=question_id,
                    answer=processed_answer,
                    score=None,  # 保存时不设置分数
                    status="草稿",  # 设置为草稿状态
                    num=0  # 设置题号
                )
            )


        if answer_records_to_add:
            db.session.add_all(answer_records_to_add)
        db.session.commit()
        return jsonify({'success': True, 'message': '草稿保存成功'})
    except Exception as e:
        db.session.rollback()
        print(f"保存草稿时发生错误: {e}")
        return jsonify({'success': False, 'message': '保存失败'}), 500


@app.route('/submit_exam/<int:exam_id>', methods=['POST'])
def submit_exam(exam_id):
    student = _get_current_student()
    if not student:
        return jsonify({'success': False, 'message': '学生不存在或未登录'}), 404

    exam = Exam.query.get(exam_id)
    if not exam:
        return jsonify({'success': False, 'message': '考试不存在'}), 404

    # 获取前端提交的答案
    payload = request.get_json() or {}
    submitted_answers = payload.get('answers', [])
    print('payload', payload)
    print('submitted_answers', submitted_answers)

    # 将提交的答案转换为方便查找的字典，键为题库ID (question_id)
    submitted_answer_map = {str(item['question_id']): item.get('answer') for item in submitted_answers if
                            'question_id' in item}

    student_id_value = int(student.id) if isinstance(student.id, str) and student.id.isdigit() else student.id

    try:
        # 1. 先删除该学生本次考试的所有旧答案，防止重复提交
        Answer.query.filter_by(exam_id=exam_id, student_id=student_id_value).delete()

        # 2. 为学生提交的每一道题创建一条新的答案记录
        answer_records_to_add = []

        # 获取试卷的所有题目，确保按顺序处理
        test_paper_records = Test_paper.query.filter_by(
            testpaper_id=exam.testpaper_id
        ).order_by(Test_paper.id).all()

        for test_paper in test_paper_records:
            question_id = test_paper.question_id
            question_id_str = str(question_id)
            submitted_answer = submitted_answer_map.get(question_id_str)

            # 处理答案数据转换
            print(f"question_id={question_id}，原始答案：{submitted_answer}，类型：{type(submitted_answer)}")

            if submitted_answer is not None:
                # 处理答案格式转换
                if isinstance(submitted_answer, list):
                    # 列表类型：['A', 'B', 'D'] → "A,B,D"
                    processed_answer = ",".join(submitted_answer)
                elif isinstance(submitted_answer, str):
                    # 字符串类型：如果是数字字符串且需要转换为数字，或者保持原样
                    if submitted_answer.isdigit():
                        processed_answer = submitted_answer  # 保持为字符串，或者用 int(submitted_answer) 转换为数字
                    else:
                        processed_answer = submitted_answer
                else:
                    # 其他类型（如数字）直接转换为字符串
                    processed_answer = str(submitted_answer)
            else:
                processed_answer = ""  # 未答题存空字符串

            standard_answer = QuestionBank.query.filter_by(id=question_id).first().answer
            standard_score = QuestionBank.query.filter_by(id=question_id).first().score

            print(f"处理后的答案: {processed_answer}, 类型: {type(processed_answer)}")

            # 创建答案记录，确保所有字段都被正确设置
            answer_records_to_add.append(
                Answer(
                    exam_id=exam_id,
                    student_id=student_id_value,
                    question_id=question_id,  # 存储题库ID
                    stu_answer=processed_answer,
                    standard_answer=standard_answer,
                    stu_score=0,  # 提交时不设置分数，批改时再设置
                    standard_score=standard_score,
                    num=0  # 设置题号
                )
            )

        # 3. 批量添加所有新记录
        if answer_records_to_add:
            db.session.add_all(answer_records_to_add)

        # 4. 更新考试状态为已结束
        exam.status = '2'  # 确保状态是字符串类型，与模型定义一致

        # 5. 统一提交事务
        db.session.commit()

    except Exception as e:
        db.session.rollback()
        print(f"提交考试时发生错误: {e}")
        return jsonify({'success': False, 'message': '提交失败，请重试。'}), 500

    # 清理 session
    session.pop('current_exam', None)

    # 更新考试进度
    exam_progress = session.get('exam_progress', {})
    exam_progress[str(exam_id)] = 'completed'
    session['exam_progress'] = exam_progress

    return jsonify({'success': True, 'message': '考试提交成功', 'redirect': url_for('Waiting_exam')})

# 注释：删除了重复的save_exam_answer函数定义，只保留上面修改后的版本
@app.route('/api/exam_schedules/<int:exam_id>', methods=['DELETE'])
def delete_exam_schedules(exam_id):
    try:
        exam = db.session.query(Exam).get(exam_id)
        if not exam:
            return jsonify({'error': '考试不存在'}), 404

        db.session.delete(exam)
        db.session.commit()
        return jsonify({'success': True, 'message': '考试已删除'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@app.route('/api/exam_schedules', methods=['GET'])
def list_exam_schedules():
    status_param = request.args.get('status')
    exam_type_param = request.args.get('exam_type', '').strip()
    class_name_param = request.args.get('class_name', '').strip()
    keyword_param = request.args.get('keyword', '').strip()

    status_filter = None
    if status_param not in (None, '', 'all'):
        try:
            status_filter = int(status_param)
        except (TypeError, ValueError):
            status_filter = None

    exams, pagination_info = _build_exam_view_models(
        status_filter=status_filter,
        exam_type_filter=exam_type_param or None,
        class_name_filter=class_name_param or None,
        keyword_filter=keyword_param or None,
        page=request.args.get('page'),
        per_page=request.args.get('per_page'),
        include_pagination=True
    )
    return jsonify({'exams': exams, 'pagination': pagination_info})


@app.route('/api/exam_records')
def get_exam_records():
    '''获取学生考试记录API'''
    try:
        stu_id = session.get('username')
        # 获取当前学生
        student = _get_current_student(stu_id)
        if not student:
            return jsonify({'success': False, 'error': '学生未登录'}), 401

        # 获取查询参数
        exam_type = request.args.get('exam_type', '')
        subject = request.args.get('subject', '')
        time_range = request.args.get('time_range', '')
        search_keyword = request.args.get('search', '')
        page = int(request.args.get('page', 1))
        page_size = int(request.args.get('page_size', 10))

        # 构建基础查询 - 获取该学生参加的所有考试
        query = db.session.query(Exam).filter(
            Exam.class_id == student.class_id,
            Exam.status == '2'  # 只查询已结束的考试
        )

        # 应用筛选条件
        if exam_type and exam_type != '全部类型':
            query = query.filter(Exam.exam_type == exam_type)

        if subject and subject != '全部学科':
            query = query.filter(Exam.subject == subject)

        # 时间范围筛选
        if time_range:
            now = datetime.now()
            if time_range == '近一周':
                threshold = now - timedelta(days=7)
            elif time_range == '近一个月':
                threshold = now - timedelta(days=30)
            elif time_range == '近三个月':
                threshold = now - timedelta(days=90)
            elif time_range == '近一年':
                threshold = now - timedelta(days=365)
            else:
                threshold = datetime.min

            query = query.filter(Exam.end_time >= threshold)

        # 搜索功能
        if search_keyword:
            query = query.filter(Exam.name.ilike(f'%{search_keyword}%'))

        # 分页查询
        pagination = query.order_by(Exam.end_time.desc()).paginate(
            page=page,
            per_page=page_size,
            error_out=False
        )
        exams = pagination.items

        # 构建返回数据
        result = []
        for exam in exams:
            # 获取学生在该考试中的答案记录
            answer_record = Answer.query.filter_by(
                exam_id=exam.id,
                student_id=student.id
            ).all()
            print(answer_record)
            # 计算总分
            total_score = 0
            for answer_record  in answer_record:
                total_score += answer_record.stu_score

            else:
                # 如果没有总分记录，计算各题分数之和
                answer_details = Answer.query.filter_by(
                    exam_id=exam.id,
                    student_id=student.id
                ).all()
                total_score = sum([a.stu_score for a in answer_details if a.stu_score is not None])
                print(total_score)

            # 获取班级平均分 - 修复这里的问题
            class_avg_score = calculate_class_avg_score(exam.id)

            # 计算班级排名 - 使用兼容MySQL的方法
            student_rank = calculate_student_rank(exam.id, student.id)

            # 获取试卷名称
            test_paper = Test2question.query.get(exam.testpaper_id)
            exam_name = test_paper.name if test_paper else exam.name

            result.append({
                'id': exam.id,
                'exam_name': exam_name,
                'exam_type': exam.exam_type,
                'subject': exam.subject,
                'exam_time': exam.end_time.strftime('%Y-%m-%d %H:%M'),
                'my_score': round(total_score, 1),
                'class_avg_score': round(class_avg_score, 1),
                'class_rank': f'第{student_rank}名' if student_rank else '未排名',
                'duration': f'{exam.exam_duration}分钟'
            })

        return jsonify({
            'success': True,
            'data': {
                'exams': result,
                'pagination': {
                    'page': page,
                    'page_size': page_size,
                    'total': pagination.total,
                    'pages': pagination.pages
                },
                'summary': {
                    'total_exams': pagination.total,
                    'avg_score': round(sum([exam['my_score'] for exam in result]) / len(result), 1) if result else 0,
                    'excellent_rate': round(
                        len([exam for exam in result if exam['my_score'] >= 85]) / len(result) * 100,
                        1) if result else 0
                }
            }
        })

    except Exception as e:
        print(f"获取考试记录时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取考试记录失败'
        }), 500

def calculate_class_avg_score(exam_id):
    """计算班级平均分（所有学生总分的平均值）"""
    try:
        # 获取参加该考试的所有学生
        student_answers = db.session.query(
            Answer.student_id,
            db.func.sum(Answer.stu_score).label('total_score')
        ).filter_by(
            exam_id=exam_id
        ).group_by(Answer.student_id).all()

        if not student_answers:
            return 0

        # 计算所有学生总分的平均值
        total_scores = [score for student_id, score in student_answers if score is not None]
        if not total_scores:
            return 0

        return sum(total_scores) / len(total_scores)

    except Exception as e:
        print(f"计算班级平均分时出错: {e}")
        return 0

def calculate_student_rank(exam_id, student_id):
    """计算学生在考试中的排名（兼容MySQL低版本）"""
    try:
        # 方法1: 使用子查询计算排名
        # 获取所有学生的总分
        student_scores = db.session.query(
            Answer.student_id,
            db.func.sum(Answer.stu_score).label('total_score')
        ).filter_by(
            exam_id=exam_id
        ).group_by(Answer.student_id).all()

        if not student_scores:
            return None

        # 将结果转换为列表并排序
        scores_list = []
        for student_id_val, total_score in student_scores:
            if total_score is not None:
                scores_list.append({
                    'student_id': student_id_val,
                    'total_score': float(total_score)
                })

        # 按分数降序排序
        scores_list.sort(key=lambda x: x['total_score'], reverse=True)

        # 计算排名（处理并列情况）
        rank = 1
        prev_score = None
        for i, score_data in enumerate(scores_list):
            current_score = score_data['total_score']
            if prev_score is not None and current_score < prev_score:
                rank = i + 1
            score_data['rank'] = rank
            prev_score = current_score

            # 如果找到目标学生，返回排名
            if score_data['student_id'] == student_id:
                return rank

        return None

    except Exception as e:
        print(f"计算排名时出错: {e}")
        return None


@app.route('/api/exam_records/filters')
def get_exam_record_filters():
    '''获取考试记录筛选条件'''
    try:
        stu_id = session.get('username')
        student = _get_current_student(stu_id)
        if not student:
            return jsonify({'success': False, 'error': '学生未登录'}), 401

        # 获取考试类型选项
        exam_types = db.session.query(Exam.exam_type).filter(
            Exam.class_id == student.class_id,
            Exam.status == '2'
        ).distinct().all()
        exam_types = [et[0] for et in exam_types if et[0]]

        # 获取学科选项
        subjects = db.session.query(Exam.subject).filter(
            Exam.class_id == student.class_id,
            Exam.status == '2'
        ).distinct().all()
        subjects = [s[0] for s in subjects if s[0]]

        return jsonify({
            'success': True,
            'data': {
                'exam_types': exam_types,
                'subjects': subjects
            }
        })

    except Exception as e:
        print(f"获取筛选条件时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取筛选条件失败'
        }), 500


@app.route('/api/exam_records/<int:exam_id>/detail')
def get_exam_record_detail(exam_id):
    '''获取考试试卷详情API'''
    try:
        stu_id = session.get('username')
        # 获取当前学生
        student = _get_current_student(stu_id)
        if not student:
            return jsonify({'success': False, 'error': '学生未登录'}), 401

        # 验证考试是否存在且该学生有权限访问
        exam = Exam.query.get(exam_id)
        if not exam or exam.class_id != student.class_id:
            return jsonify({'success': False, 'error': '考试不存在或无权限访问'}), 404

        # 获取试卷基本信息
        test_paper = Test2question.query.get(exam.testpaper_id)
        if not test_paper:
            return jsonify({'success': False, 'error': '试卷不存在'}), 404

        # 获取考试题目
        question_rows = (
            db.session.query(Test_paper, QuestionBank)
            .outerjoin(QuestionBank, Test_paper.question_id == QuestionBank.id)
            .filter(Test_paper.testpaper_id == exam.testpaper_id)
            .order_by(Test_paper.id.asc())
            .all()
        )
        print(question_rows)
        # 获取学生答案
        student_answers = Answer.query.filter_by(
            exam_id=exam_id,
            student_id=student.id
        ).all()

        # 创建答案映射 {question_id: answer}
        answer_map={}
        for answer in student_answers:
            answer_map[str(answer.question_id)] = answer
            print(answer_map)
        # 处理题目数据
        questions = []
        for detail, question in question_rows:
            # 获取题目文本
            question_text = question.title if question else detail.question_id
            print(question_text)
            # 解析选项
            option_payload = detail.option or (question.option if question else None)
            options = _parse_options(option_payload)

            # 获取题目类型
            question_type = detail.type or (question.type if question else '')
            print(question.id)
            # 获取学生答案
            detail_id_str = str(question.id)
            print(detail_id_str)
            student_answer = answer_map.get(detail_id_str)
            print(student_answer)
            student_answer_text = student_answer.stu_answer if student_answer else None
            question_score = student_answer.stu_score if student_answer else 0

            # 判断是否正确
            is_correct = False
            if student_answer_text and detail.answer:
                if question_type == '多选题':
                    # 多选题答案比较（排序后比较）
                    student_ans_sorted = ''.join(sorted(student_answer_text.upper()))
                    correct_ans_sorted = ''.join(sorted(detail.answer.upper()))
                    is_correct = student_ans_sorted == correct_ans_sorted
                else:
                    is_correct = student_answer_text.upper() == detail.answer.upper()

            questions.append({
                'id': detail.id,
                'question': question_text,
                'type': question_type,
                'options': options,
                'correct_answer': detail.answer,
                'student_answer': student_answer_text,
                'score': question_score,
                'max_score': detail.score,
                'is_correct': is_correct
            })

        # 计算总分
        total_score = sum([q['score'] for q in questions])
        max_total_score = sum([q['max_score'] for q in questions])

        return jsonify({
            'success': True,
            'data': {
                'exam': {
                    'id': exam.id,
                    'name': test_paper.name if test_paper else exam.name,
                    'exam_type': exam.exam_type,
                    'subject': exam.subject,
                    'exam_time': exam.end_time.strftime('%Y-%m-%d %H:%M') if exam.end_time else '',
                    'total_score': total_score,
                    'max_total_score': max_total_score
                },
                'questions': questions
            }
        })

    except Exception as e:
        print(f"获取考试详情时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取考试详情失败'
        }), 500


@app.route('/api/exam_records/trend')
def get_exam_score_trend():
    '''获取成绩趋势数据'''
    try:
        stu_id = session.get('username')
        student = _get_current_student(stu_id)
        if not student:
            return jsonify({'success': False, 'error': '学生未登录'}), 401

        # 获取最近的考试记录（按时间倒序，取前7次）
        exams = db.session.query(Exam).filter(
            Exam.class_id == student.class_id,
            Exam.status == '2'
        ).order_by(Exam.end_time.desc()).limit(7).all()

        # 反转顺序，让时间从早到晚
        exams.reverse()

        labels = []
        student_scores = []
        class_avg_scores = []

        for exam in exams:
            # 获取学生分数
            answer_record = Answer.query.filter_by(
                exam_id=exam.id,
                student_id=student.id
            ).all()

            student_score = 0

            student_score = sum([a.stu_score for a in answer_record if a.stu_score is not None])

            # 获取班级平均分
            class_avg_score = calculate_class_avg_score(exam.id)

            # 获取试卷名称作为标签
            test_paper = Test2question.query.get(exam.testpaper_id)
            exam_name = test_paper.name if test_paper else f"考试_{exam.id}"

            labels.append(exam_name)
            student_scores.append(round(student_score, 1))
            class_avg_scores.append(round(class_avg_score, 1))

        return jsonify({
            'success': True,
            'data': {
                'labels': labels,
                'student_scores': student_scores,
                'class_avg_scores': class_avg_scores
            }
        })

    except Exception as e:
        print(f"获取成绩趋势时出错: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取成绩趋势失败'
        }), 500

@app.route('/',methods=['GET','POST'])
def login():
    '''登录'''
    if request.method == 'GET':
        return render_template('login.html')
    try:
        data = request.form
        username = data['username']
        password = data['password']
        Identity = data['Identity']
        if Identity == '教师':
            password2 = Teacher.query.filter(Teacher.id == username).first().password
            if password == password2:
                session['username'] = username
                session['identity'] = Identity
                return jsonify({'success': True,'redirect': url_for('index', identity=Identity, username=username)})
            else:
                return jsonify({'success': False, 'error': '账号或密码错误'}), 404

        if Identity == '学生':
            password2 = Student.query.filter(Student.id == username).first().password
            if password == password2:
                session['username'] = username
                session['identity'] = Identity
                return jsonify({'success': True,'redirect': url_for('index', identity=Identity, username=username)})
            else:
                return jsonify({'success': False, 'error': '账号或密码错误'}), 404

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 404

@app.route('/register',methods=['GET','POST'])
def register():
    '''注册'''
    if request.method == 'GET':
        return render_template('register.html')
    try:
        data = request.form
        name = data['name']
        age = data['age']
        gender = data['gender']
        job = data['job']
        password = data['password']
        teacher = Teacher.query.filter(Teacher.name == name).first()
        if teacher is not None:
            return jsonify({'success': False, 'error': '名字发生重复请在姓名后添加数字'}), 404
        new_teacher = Teacher(name=name,age=age,gender=gender,job=job,password=password)
        db.session.add(new_teacher)
        db.session.commit()
        new_id = Teacher.query.filter(Teacher.name == name).first().id
        return jsonify({'success': True,'redirect': url_for('login'),'username':new_id})


    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 404

if __name__ == '__main__':
    app.run()
